
// 闭包生成带有属性的函数
let wxhttp: $request = function () {
  let reqSet: $reqSet = {
    url: '',
    method: 'GET',
    data: {},
    params: {},
    headers: {},
    dataType: 'json',
    interRequest: undefined, //拦截的请求方法
    interRequesError: undefined, //请求拦截出错时的处理
    interResponse: undefined //拦截的返回方法
  }

  // 返回的函数
  /*
  1. url为字符串
  2. url为对象设置
  3. data为非get方法的设置时
  4. data为非get方法的数据时
  5. data为get方法的设置时
   */

  //  核心请求方法
  let request: $request = function (url: string | anyObj | $reqSet, config: anyObj | $reqSet = {}): any {
    let _data = {}
    // 判断url类型，根据类型初始化seqSet
    switch (true) {
      case typeof url == 'string':
        url = (<string>url).trim();
        ((<anyObj>config)).params = ((<anyObj>config)).params || {}
        Object.assign(_data, ((<anyObj>config)).params)
        Object.assign(reqSet, config, {
          url
        })
        break
      case typeof url == 'object':
        (<anyObj>url).params = (<anyObj>url).params || {}
        Object.assign(_data, (<anyObj>url).params)
        Object.assign(reqSet, url)
        break
      default:
        throw new Error('请传入正确的参数')
    }

    // 请求拦截
    if (reqSet.interRequest) {
      // 对数据进行合并
      /* _data = {
        ..._data
      } */
      try {
        let config = reqSet.interRequest(reqSet)
        Object.assign(_data, (config.method == 'GET' ? config.params : config.data))
      } catch (error) {
        console.error('拦截请求出错', 'wxHttp', 119, error)
        if (reqSet.interRequesError) {
          reqSet.interRequesError(error)
        }
      }
    }

    // 返回promise的操作
    return new Promise((reso, rej) => {
      // 每次请求的独立请求参数
      let tempReq: null | anyObj = {}
      Object.assign(tempReq, reqSet, {header: reqSet.headers})
      // 重置
      // 任何一个方法请求完成后恢复数据
      Object.assign(reqSet, {
        method: 'GET',
        data: {},
        url: '',
        header: {},
        headers: {},
        dataType: 'json'
      })
      wx.request({
        ...tempReq,
        data: _data,
        success (res: any) {
          // 返回拦截
          if (reqSet.interResponse) reqSet.interResponse(res)
          reso(res)
        },
        fail (err: Error) {
          rej(err)
        },
        complete () {
          tempReq = null
        }
      })
    })
  }

  // get方法
  request.get = function (url: string | any, config: any = {}) {
    Object.assign(reqSet, config, {
      url,
      method: 'GET'
    })
    return request(reqSet)
  }

  // delete,head,options方法
  let methodsArr1 = [
    [ 'delete', 'DELETE' ],
    [ 'head', 'HEAD' ],
    [ 'options', 'OPTIONS' ]
  ]
  for (let [ name, method ] of methodsArr1) {
    request[ name ] = function (url: string, config: anyObj) {
      config = config || {}
      Object.assign(reqSet, config, {
        url,
        method
      })
      return request(reqSet)
    }
  }

  // post,put等其他方法
  let methodsArr2 = [
    [ 'put', 'PUT' ],
    [ 'post', 'POST' ]
  ]
  for (let [ name, method ] of methodsArr2) {
    request[ name ] = function (url: string, data: any, config: $reqSet | boolean = false) {
      if (config) {
        Object.assign(reqSet, config, {
          url,
          params: (<$reqSet>config).data,
          method
        })
      } else {
        Object.assign(reqSet, {
          url,
          params: data,
          method
        })
      }
      return request(reqSet)
    }
  }

  // 添加拦截方法
  request.interceptors = {
    // 请求的拦截方法
    request: {
      use (handleRequest: $interRequest, handleError: $interRequesError) {
        try {
          reqSet.interRequest = handleRequest
          reqSet.interRequesError = handleError
        } catch (error) {
          handleError(error)
        }
      }
    },
    // 返回的拦截方法
    response: {
      use (handle: $interResponse) {
        try {
          reqSet.interResponse = handle
        } catch (error) {
          console.error(`处理返回拦截出错`)
        }
      }
    }
  }
  // 返回请求的东西
  return request
}()

export default wxhttp
export {
  wxhttp
}
